using System.Diagnostics;
using AForge.Video.DirectShow;
using VideoRecorder.Media;
using VideoRecorder.Util;
using VideoRecorder.VM;
using MessageBox = System.Windows.Forms.MessageBox;

namespace VideoRecorder;

public class MainWindowVM : BaseVM {
    private const string TAG = $"[{nameof(MainWindowVM)}]";

    private FilterInfo _selectedCamera;
    private string _recordedTime = "00:00:00";
    private readonly TimedIntervalTask _refreshTimeTask;
    private Stopwatch _cameraStopwatch;
    private readonly TimeLogger _log = new();

    private WebCamInfo[] _deviceCapabilities;
    private WebCamInfo? _selectedResolution;
    private Screen _selectedScreen = Screen.PrimaryScreen;

    public List<FilterInfo> Devices { get; } =
        new FilterInfoCollection(FilterCategory.VideoInputDevice).Cast<FilterInfo>().ToList();

    public FilterInfo SelectedCamera {
        get => _selectedCamera;
        set {
            if (SetField(ref _selectedCamera, value)) {
                DeviceCapabilities = WebCamHelper.GetCameraInfos(value.Name).ToArray();
                SelectedResolution = WebCamHelper.GetPreferCameraInfo(DeviceCapabilities);
            }
        }
    }

    public WebCamInfo[] DeviceCapabilities {
        get => _deviceCapabilities;
        set => SetField(ref _deviceCapabilities, value);
    }

    public WebCamInfo? SelectedResolution {
        get => _selectedResolution;
        set {
            if (SetField(ref _selectedResolution, value)) {
                OnPropertyChanged(nameof(FrameWidth));
                OnPropertyChanged(nameof(FrameHeight));

                if (IsRunning && value != null) {
                    Task.Run(async () => {
                        CloseCamera();
                        await Task.Delay(1000);
                        OpenCamera();
                    });
                }
            }
        }
    }

    public Screen SelectedScreen {
        get => _selectedScreen;
        set {
            if (SetField(ref _selectedScreen, value)) {
                ScreenCapture.Screen = value;
                OnPropertyChanged(nameof(FrameWidth));
                OnPropertyChanged(nameof(FrameHeight));
            }
        }
    }

    public int FrameWidth => IsScreenCapture ? SelectedScreen.Bounds.Width : SelectedResolution?.Width ?? 800;
    public int FrameHeight => IsScreenCapture ? SelectedScreen.Bounds.Height : SelectedResolution?.Height ?? 600;
    public int Fps => IsScreenCapture ? ScreenCapture.Fps : SelectedResolution?.Fps ?? 30;

    public bool IsScreenCapture {
        get => _isScreenCapture;
        set {
            if (SetField(ref _isScreenCapture, value)) {
                OnPropertyChanged(nameof(FrameWidth));
                OnPropertyChanged(nameof(FrameHeight));
            }
        }
    }

    public CvCamera Camera { get; } = new();
    public ScreenCapturer ScreenCapture { get; } = new();
    public readonly CvVideoWriter Recorder = new();
    private bool _isRecording;
    private bool _isScreenCapture;


    public string RecordedTime {
        get => _recordedTime;
        set => SetField(ref _recordedTime, value);
    }

    public bool IsRunning => IsScreenCapture ? ScreenCapture.IsRunning : Camera.IsRunning;
    public bool IsRecording {
        get => _isRecording;
        set => SetField(ref _isRecording, value);
    }

    public MainWindowVM() {
        _refreshTimeTask = new TimedIntervalTask(RefreshRecordedTime, 200);
    }

    private void RefreshRecordedTime() {
        var ts = TimeSpan.FromSeconds(Recorder.TotalFrames / (double)Fps);
        RecordedTime = $"{ts.Hours:D2}:{ts.Minutes:D2}:{ts.Seconds:D2}";
    }

    public void OpenCamera() {
        if (Camera.IsRunning) return;
        if (SelectedCamera == null) {
            MessageBox.Show("请选择摄像头");
            return;
        }

        var index = Devices.FindIndex(it => it == SelectedCamera);
        if (index < 0) {
            MessageBox.Show("没有找到摄像头");
            return;
        }

        Camera.Index = index;
        Camera.Width = FrameWidth;
        Camera.Height = FrameHeight;
        Camera.Fps = Fps;

        Camera.Start();
        _cameraStopwatch = Stopwatch.StartNew();
    }

    public void CloseCamera() {
        if (!Camera.IsRunning) return;
        Camera.Stop();
        _cameraStopwatch?.Stop();
    }

    public void StartScreenCapture() {
        if (SelectedScreen == null) {
            MessageBox.Show("请选择屏幕");
            return;
        }

        ScreenCapture.Screen = SelectedScreen;
        ScreenCapture.Start();
    }

    public void StopScreenCapture() {
        if (!ScreenCapture.IsRunning) return;
        ScreenCapture.Stop();
    }

    public void StartRecord() {
        if (IsRecording) return;
        IsRecording = true;
        var outputFile = $"Record-{DateTime.Now:yyyyMMdd_HHmmss}.mp4";
        Recorder.Open(outputFile, FrameWidth, FrameHeight, Fps);
        _refreshTimeTask.Startup();
    }

    public void StopRecord() {
        if (!IsRecording) return;
        IsRecording = false;
        _refreshTimeTask.Stop();
        Recorder.Close();
    }
}
